import { strings } from "../..";

/**
 * 计算树状结构的最大深度
 * 
 * @template T - 树节点类型，必须是包含子节点的对象类型
 * @param {T[]} items - 树状结构的根节点数组
 * @param {number} [currentLevel=1] - 当前层级，默认为1（根节点层级）
 * @param {string} [childrenKey='children'] - 子节点在对象中的键名，默认为'children'
 * @returns {number} - 树状结构的最大深度
 * 
 * @example
 * // 基本用法：计算简单树的深度
 * const simpleTree = [
 *   { name: 'Node 1', children: [{ name: 'Node 1-1' }] }
 * ];
 * const simpleDepth = depth(simpleTree); // 返回 2
 * 
 * @example
 * // 自定义子节点键名
 * const customTree = [
 *   { name: 'Item 1', subItems: [{ name: 'Item 1-1', subItems: [{ name: 'Item 1-1-1' }] }] }
 * ];
 * const customDepth = depth(customTree, 1, 'subItems'); // 返回 3
 */
export function depth<T extends Record<string, any>>(items: T[], currentLevel = 1, childrenKey: string = 'children'): number {
  let maxLevel = currentLevel;

  items.forEach(item => {
    if (item[childrenKey] && Array.isArray(item[childrenKey]) && item[childrenKey].length > 0) {
      const level = depth(item[childrenKey], currentLevel + 1, childrenKey);
      maxLevel = Math.max(maxLevel, level);
    }
  });

  return maxLevel;
}

/**
 * 计算树状结构中的叶子节点数量
 * 
 * @template T - 树节点类型，必须是包含子节点的对象类型
 * @param {T[]} items - 树状结构的节点数组
 * @param {string} [childrenKey='children'] - 子节点在对象中的键名，默认为'children'
 * @returns {number} - 叶子节点的总数
 * 
 * @example
 * // 基本用法：计算简单树的叶子节点数量
 * const simpleTree = [
 *   { name: 'Node 1', children: [{ name: 'Node 1-1' }] },
 *   { name: 'Node 2' }
 * ];
 * const leafCount = countLeaves(simpleTree); // 返回 2
 * 
 * @example
 * // 自定义子节点键名
 * const customTree = [
 *   { name: 'Item 1', subItems: [{ name: 'Item 1-1' }] },
 *   { name: 'Item 2' }
 * ];
 * const customCount = countLeaves(customTree, 'subItems'); // 返回 2
 */
export function countLeaves<T extends Record<string, any>>(items: T[], childrenKey: string = 'children'): number {
  let count = 0;

  items.forEach(item => {
    if (item[childrenKey] && Array.isArray(item[childrenKey]) && item[childrenKey].length > 0) {
      count += countLeaves(item[childrenKey], childrenKey);
    } else {
      count++;
    }
  });

  return count;
}

/**
 * 获取树状结构中的所有叶子节点
 * 
 * @template T - 树节点类型，必须是包含子节点的对象类型
 * @param {T[]} items - 树状结构的节点数组
 * @param {string} [childrenKey='children'] - 子节点在对象中的键名，默认为'children'
 * @returns {T[]} - 叶子节点的数组
 * 
 * @example
 * // 基本用法：获取简单树的所有叶子节点
 * const simpleTree = [
 *   { name: 'Node 1', children: [{ name: 'Node 1-1' }] },
 *   { name: 'Node 2' }
 * ];
 * const leaves = leafs(simpleTree); // 返回 [{ name: 'Node 1-1' }, { name: 'Node 2' }]
 * 
 * @example
 * // 自定义子节点键名
 * const customTree = [
 *   { name: 'Item 1', subItems: [{ name: 'Item 1-1' }] },
 *   { name: 'Item 2' }
 * ];
 * const customLeaves = leafs(customTree, 'subItems'); // 返回 [{ name: 'Item 1-1' }, { name: 'Item 2' }]
 */
export function leafs<T extends Record<string, any>>(items: T[], childrenKey: string = 'children'): T[] {
  const leafNodes: T[] = [];

  const findLeafs = (treeItems: T[]) => {
    treeItems.forEach(item => {
      if (item[childrenKey] && Array.isArray(item[childrenKey]) && item[childrenKey].length > 0) {
        findLeafs(item[childrenKey]);
      } else {
        leafNodes.push(item);
      }
    });
  };

  if (items && items.length > 0) {
    findLeafs(items);
  }

  return leafNodes;
}

/**
 * 获取带层级分隔符的索引及其所有父索引
 * 
 * @param {string} index - 带层级分隔符的索引字符串（如 'a.b.c'）
 * @param {string} [separator='.'] - 层级分隔符，默认为 '.'
 * @returns {Set<string>} - 包含当前索引及其所有父索引的集合
 * 
 * @example
 * // 基本用法
 * const indexes = getAllParentIndexes('a.b.c');
 * // 返回: Set { 'a.b.c', 'a.b', 'a' }
 * 
 * @example
 * // 自定义分隔符
 * const customIndexes = getAllParentIndexes('a/b/c', '/');
 * // 返回: Set { 'a/b/c', 'a/b', 'a' }
 */
export function getAllParentIndexes(index: string, separator: string = '.'): Set<string> {
  const indexesSet = new Set<string>();
  indexesSet.add(strings.chain(index).trim(separator).toString());
  
  let currentIndex = index;
  while (true) {
    // 查找最后一个分隔符的位置
    const lastSeparatorIndex = currentIndex.lastIndexOf(separator);
    if (lastSeparatorIndex === -1) break;
    
    // 获取父索引
    currentIndex = currentIndex.substring(0, lastSeparatorIndex);
    indexesSet.add(currentIndex);
  }
  
  return indexesSet;
}